using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RiceShop.Models;
using System.Text.Json;
using admin_webapi.Utils;

namespace RiceShop.Services
{
    /// <summary>
    /// Paylinks支付服务实现
    /// </summary>
    public class PaylinksPaymentService : IPaylinksPaymentService
    {
        private readonly ApplicationDbContext _context;
        private readonly ILogger<PaylinksPaymentService> _logger;
        private readonly PaylinksConfig _config;

        public PaylinksPaymentService(
            ApplicationDbContext context,
            ILogger<PaylinksPaymentService> logger,
            IOptions<PaylinksConfig> config)
        {
            _context = context;
            _logger = logger;
            _config = config.Value;
        }

        /// <summary>
        /// 创建小程序支付订单
        /// </summary>
        public async Task<PaymentInfo> CreateMiniProgramPaymentAsync(string orderNo, long userId, string openId)
        {
            try
            {
                // 获取订单信息
                var order = await GetOrderByOrderNoAsync(orderNo);
                if (order == null)
                    throw new Exception("订单不存在");

                if (order.Status != OrderStatus.Pending)
                    throw new Exception("订单状态不正确，只有待支付订单可以支付");

                // 创建支付记录
                var paymentRecord = await CreatePaymentRecordAsync(order, "MINI_PROGRAM");

                // 生成预支付交易会话标识
                var prepayId = $"wx_prepay_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                
                // 更新支付记录
                paymentRecord.PrepayId = prepayId;
                await _context.SaveChangesAsync();

                // 构建签名参数
                string timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
                string nonceStr = Guid.NewGuid().ToString("N");
                string package = $"prepay_id={prepayId}";
                
                // 按微信支付规则拼接签名字符串
                string message = $"{_config.WeChatPay.AppId}\n{timestamp}\n{nonceStr}\n{package}\n";
                
                // 使用商户私钥进行签名
                string paySign = SignatureHelper.SignWithRsa(message, _config.WeChatPay.MchPrivateKey);

                return new PaymentInfo
                {
                    OrderNo = orderNo,
                    Amount = order.PayAmount,
                    TimeStamp = timestamp,
                    NonceStr = nonceStr,
                    Package = package,
                    SignType = "RSA",
                    PaySign = paySign
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建小程序支付订单失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 创建APP支付订单
        /// </summary>
        public async Task<PaymentInfo> CreateAppPaymentAsync(string orderNo, long userId)
        {
            try
            {
                // 获取订单信息
                var order = await GetOrderByOrderNoAsync(orderNo);
                if (order == null)
                    throw new Exception("订单不存在");

                if (order.Status != OrderStatus.Pending)
                    throw new Exception("订单状态不正确，只有待支付订单可以支付");

                // 创建支付记录
                var paymentRecord = await CreatePaymentRecordAsync(order, "APP");

                // 生成预支付交易会话标识
                var prepayId = $"wx_prepay_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                
                // 更新支付记录
                paymentRecord.PrepayId = prepayId;
                await _context.SaveChangesAsync();

                // 构建签名参数
                string timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
                string nonceStr = Guid.NewGuid().ToString("N");
                string package = "Sign=WXPay";
                
                // 按微信支付规则拼接签名字符串
                string message = $"{_config.WeChatPay.AppId}\n{timestamp}\n{nonceStr}\n{package}\n";
                
                // 使用商户私钥进行签名
                string paySign = SignatureHelper.SignWithRsa(message, _config.WeChatPay.MchPrivateKey);

                return new PaymentInfo
                {
                    OrderNo = orderNo,
                    Amount = order.PayAmount,
                    TimeStamp = timestamp,
                    NonceStr = nonceStr,
                    Package = package,
                    SignType = "RSA",
                    PaySign = paySign
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建APP支付订单失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 创建H5支付订单
        /// </summary>
        public async Task<PaymentInfo> CreateH5PaymentAsync(string orderNo, long userId, string clientIp)
        {
            try
            {
                // 获取订单信息
                var order = await GetOrderByOrderNoAsync(orderNo);
                if (order == null)
                    throw new Exception("订单不存在");

                if (order.Status != OrderStatus.Pending)
                    throw new Exception("订单状态不正确，只有待支付订单可以支付");

                // 创建支付记录
                var paymentRecord = await CreatePaymentRecordAsync(order, "H5");

                // 生成预支付交易会话标识
                var prepayId = $"wx_prepay_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                
                // 更新支付记录
                paymentRecord.PrepayId = prepayId;
                await _context.SaveChangesAsync();

                // 构建签名参数
                string timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
                string nonceStr = Guid.NewGuid().ToString("N");
                string package = $"prepay_id={prepayId}";
                
                // 按微信支付规则拼接签名字符串
                string message = $"{_config.WeChatPay.AppId}\n{timestamp}\n{nonceStr}\n{package}\n";
                
                // 使用商户私钥进行签名
                string paySign = SignatureHelper.SignWithRsa(message, _config.WeChatPay.MchPrivateKey);

                return new PaymentInfo
                {
                    OrderNo = orderNo,
                    Amount = order.PayAmount,
                    PaymentUrl = $"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id={prepayId}",
                    TimeStamp = timestamp,
                    NonceStr = nonceStr,
                    Package = package,
                    SignType = "RSA",
                    PaySign = paySign
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建H5支付订单失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 创建支付宝APP支付订单
        /// </summary>
        public async Task<PaymentInfo> CreateAlipayAppPaymentAsync(string orderNo, long userId)
        {
            try
            {
                // 获取订单信息
                var order = await GetOrderByOrderNoAsync(orderNo);
                if (order == null)
                    throw new Exception("订单不存在");

                if (order.Status != OrderStatus.Pending)
                    throw new Exception("订单状态不正确，只有待支付订单可以支付");

                // 创建支付记录
                var paymentRecord = await CreatePaymentRecordAsync(order, "ALIPAY_APP");

                // 生成支付宝交易号
                var tradeNo = $"alipay_trade_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                
                // 更新支付记录
                paymentRecord.PrepayId = tradeNo;
                await _context.SaveChangesAsync();

                return new PaymentInfo
                {
                    OrderNo = orderNo,
                    Amount = order.PayAmount,
                    TimeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
                    NonceStr = Guid.NewGuid().ToString("N"),
                    Package = BuildAlipayPackage(order, paymentRecord, _config.Alipay.AppId),
                    SignType = "RSA2",
                    PaySign = SignatureHelper.SignWithRsa(BuildAlipaySignContent(order, paymentRecord), _config.Alipay.AppPrivateKey)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建支付宝APP支付订单失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 创建支付宝H5支付订单
        /// </summary>
        public async Task<PaymentInfo> CreateAlipayH5PaymentAsync(string orderNo, long userId, string clientIp)
        {
            try
            {
                // 获取订单信息
                var order = await GetOrderByOrderNoAsync(orderNo);
                if (order == null)
                    throw new Exception("订单不存在");

                if (order.Status != OrderStatus.Pending)
                    throw new Exception("订单状态不正确，只有待支付订单可以支付");

                // 创建支付记录
                var paymentRecord = await CreatePaymentRecordAsync(order, "ALIPAY_H5");

                // 生成支付宝交易号
                var tradeNo = $"alipay_trade_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                
                // 更新支付记录
                paymentRecord.PrepayId = tradeNo;
                await _context.SaveChangesAsync();

                return new PaymentInfo
                {
                    OrderNo = orderNo,
                    Amount = order.PayAmount,
                    PaymentUrl = BuildAlipayH5Url(order, paymentRecord, _config.Alipay.AppId),
                    TimeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
                    NonceStr = Guid.NewGuid().ToString("N"),
                    Package = $"alipay_trade_no={tradeNo}",
                    SignType = "RSA2",
                    PaySign = SignatureHelper.SignWithRsa(BuildAlipayH5SignContent(order, paymentRecord), _config.Alipay.AppPrivateKey)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建支付宝H5支付订单失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 处理支付回调
        /// </summary>
        public async Task<bool> HandlePaymentNotifyAsync(string notifyData)
        {
            try
            {
                _logger.LogInformation("收到支付回调: {NotifyData}", notifyData);

                // 解析回调数据
                var notify = JsonSerializer.Deserialize<WeChatPayNotify>(notifyData);
                if (notify == null)
                {
                    _logger.LogError("支付回调数据解析失败");
                    return false;
                }

                // 验证签名（实际项目中需要实现真实的签名验证）
                if (!VerifyNotifySignature(notifyData))
                {
                    _logger.LogError("支付回调签名验证失败");
                    return false;
                }

                // 查找支付记录
                var paymentRecord = await _context.PaymentRecords
                    .FirstOrDefaultAsync(p => p.PaymentNo == notify.OutTradeNo);

                if (paymentRecord == null)
                {
                    _logger.LogError("支付记录不存在: {PaymentNo}", notify.OutTradeNo);
                    return false;
                }

                // 更新支付记录
                paymentRecord.PaymentStatus = (int)PaymentStatus.Success;
                paymentRecord.TransactionId = notify.TransactionId;
                paymentRecord.PaymentTime = DateTime.Now;
                paymentRecord.UpdateTime = DateTime.Now;

                // 更新订单状态
                var order = await _context.Orders
                    .FirstOrDefaultAsync(o => o.OrderNo == paymentRecord.OrderNo);

                if (order != null)
                {
                    order.Status = OrderStatus.Shipping;
                    order.PayTime = DateTime.Now;
                    order.TransactionId = notify.TransactionId;
                    order.UpdateTime = DateTime.Now;
                }

                await _context.SaveChangesAsync();

                _logger.LogInformation("支付回调处理成功: {OrderNo}", paymentRecord.OrderNo);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理支付回调失败");
                return false;
            }
        }

        /// <summary>
        /// 查询支付状态
        /// </summary>
        public async Task<PaymentQueryResult> QueryPaymentStatusAsync(string orderNo)
        {
            try
            {
                var paymentRecord = await _context.PaymentRecords
                    .FirstOrDefaultAsync(p => p.OrderNo == orderNo);

                if (paymentRecord == null)
                    return new PaymentQueryResult { TradeState = "NOT_FOUND" };

                // 获取支付状态
                var tradeState = paymentRecord.PaymentStatus == (int)PaymentStatus.Success ? "SUCCESS" : "NOTPAY";
                
                return new PaymentQueryResult
                {
                    OrderNo = orderNo,
                    TradeState = tradeState,
                    TradeStateDesc = GetTradeStateDesc(tradeState),
                    TransactionId = paymentRecord.TransactionId,
                    SuccessTime = paymentRecord.PaymentTime?.ToString("yyyy-MM-dd HH:mm:ss")
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询支付状态失败: {OrderNo}", orderNo);
                return new PaymentQueryResult { TradeState = "ERROR" };
            }
        }

        /// <summary>
        /// 关闭支付订单
        /// </summary>
        public async Task<bool> ClosePaymentAsync(string orderNo)
        {
            try
            {
                var paymentRecord = await _context.PaymentRecords
                    .FirstOrDefaultAsync(p => p.OrderNo == orderNo);

                if (paymentRecord == null)
                    return false;

                // 设置支付订单状态为已关闭
                paymentRecord.PaymentStatus = (int)PaymentStatus.Closed;
                paymentRecord.UpdateTime = DateTime.Now;
                await _context.SaveChangesAsync();
                
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "关闭支付订单失败: {OrderNo}", orderNo);
                return false;
            }
        }

        /// <summary>
        /// 申请退款
        /// </summary>
        public async Task<RefundRecord> ApplyRefundAsync(string orderNo, decimal refundAmount, string refundReason)
        {
            try
            {
                var paymentRecord = await _context.PaymentRecords
                    .FirstOrDefaultAsync(p => p.OrderNo == orderNo);

                if (paymentRecord == null)
                    throw new Exception("支付记录不存在");

                // 创建退款记录
                var refundRecord = new RefundRecord
                {
                    OrderId = paymentRecord.OrderId,
                    PaymentId = paymentRecord.PaymentId,
                    OrderNo = orderNo,
                    RefundNo = $"REF{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}",
                    RefundAmount = refundAmount,
                    RefundStatus = 0, // 处理中
                    RefundReason = refundReason,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now
                };

                _context.RefundRecords.Add(refundRecord);

                // 生成退款单号
                refundRecord.WxRefundId = $"wx_refund_{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
                await _context.SaveChangesAsync();
                
                return refundRecord;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "申请退款失败: {OrderNo}", orderNo);
                throw;
            }
        }

        /// <summary>
        /// 处理退款回调
        /// </summary>
        public async Task<bool> HandleRefundNotifyAsync(string notifyData)
        {
            try
            {
                _logger.LogInformation("收到退款回调: {NotifyData}", notifyData);

                // 解析回调数据
                var notify = JsonSerializer.Deserialize<WeChatPayRefundNotify>(notifyData);
                if (notify == null)
                {
                    _logger.LogError("退款回调数据解析失败");
                    return false;
                }

                // 验证签名（实际项目中需要实现真实的签名验证）
                if (!VerifyNotifySignature(notifyData))
                {
                    _logger.LogError("退款回调签名验证失败");
                    return false;
                }

                // 查找退款记录
                var refundRecord = await _context.RefundRecords
                    .FirstOrDefaultAsync(r => r.RefundNo == notify.OutRefundNo);

                if (refundRecord == null)
                {
                    _logger.LogError("退款记录不存在: {RefundNo}", notify.OutRefundNo);
                    return false;
                }

                // 更新退款记录
                refundRecord.RefundStatus = notify.RefundStatus == "SUCCESS" ? 1 : 2;
                refundRecord.RefundTime = DateTime.Now;
                refundRecord.UpdateTime = DateTime.Now;

                await _context.SaveChangesAsync();

                _logger.LogInformation("退款回调处理成功: {RefundNo}", refundRecord.RefundNo);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理退款回调失败");
                return false;
            }
        }

        /// <summary>
        /// 查询退款状态
        /// </summary>
        public async Task<RefundRecord?> QueryRefundStatusAsync(string refundNo)
        {
            try
            {
                var refundRecord = await _context.RefundRecords
                    .FirstOrDefaultAsync(r => r.RefundNo == refundNo);

                if (refundRecord == null)
                    return null;

                // 获取退款状态
                refundRecord.RefundStatus = Random.Shared.Next(0, 3); // 0-处理中, 1-成功, 2-失败
                refundRecord.UpdateTime = DateTime.Now;
                await _context.SaveChangesAsync();

                return refundRecord;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询退款状态失败: {RefundNo}", refundNo);
                return null;
            }
        }

        #region 私有方法

        /// <summary>
        /// 构建支付宝请求包
        /// </summary>
        private string BuildAlipayPackage(Order order, PaymentRecord paymentRecord, string appId)
        {
            var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var bizContent = System.Text.Json.JsonSerializer.Serialize(new
            {
                timeout_express = "30m",
                product_code = "QUICK_MSECURITY_PAY",
                total_amount = order.PayAmount.ToString("0.00"),
                subject = "订单支付",
                body = "订单支付",
                out_trade_no = paymentRecord.PaymentNo
            });
            
            return $"alipay_sdk=alipay-sdk-java-dynamicVersion" +
                   $"&app_id={appId}" +
                   $"&biz_content={Uri.EscapeDataString(bizContent)}" +
                   "&charset=utf-8" +
                   "&format=json" +
                   "&method=alipay.trade.app.pay" +
                   "&notify_url=https://your-domain.com/api/paylinks/alipay-notify" +
                   "&sign_type=RSA2" +
                   $"&timestamp={Uri.EscapeDataString(timestamp)}" +
                   "&version=1.0";
        }

        /// <summary>
        /// 构建支付宝签名内容
        /// </summary>
        private string BuildAlipaySignContent(Order order, PaymentRecord paymentRecord)
        {
            var parameters = new SortedDictionary<string, string>
            {
                ["app_id"] = _config.Alipay.AppId,
                ["biz_content"] = System.Text.Json.JsonSerializer.Serialize(new
                {
                    timeout_express = "30m",
                    product_code = "QUICK_MSECURITY_PAY",
                    total_amount = order.PayAmount.ToString("0.00"),
                    subject = "订单支付",
                    body = "订单支付",
                    out_trade_no = paymentRecord.PaymentNo
                }),
                ["charset"] = "utf-8",
                ["format"] = "json",
                ["method"] = "alipay.trade.app.pay",
                ["notify_url"] = "https://your-domain.com/api/paylinks/alipay-notify",
                ["sign_type"] = "RSA2",
                ["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                ["version"] = "1.0"
            };

            return string.Join("&", parameters.Select(p => $"{p.Key}={p.Value}"));
        }

        /// <summary>
        /// 构建支付宝H5支付URL
        /// </summary>
        private string BuildAlipayH5Url(Order order, PaymentRecord paymentRecord, string appId)
        {
            var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var bizContent = System.Text.Json.JsonSerializer.Serialize(new
            {
                out_trade_no = paymentRecord.PaymentNo,
                product_code = "QUICK_WAP_WAY",
                total_amount = order.PayAmount.ToString("0.00"),
                subject = "订单支付"
            });

            var signContent = BuildAlipayH5SignContent(order, paymentRecord);
            var sign = SignatureHelper.SignWithRsa(signContent, _config.Alipay.AppPrivateKey);

            return $"https://openapi.alipay.com/gateway.do?" +
                   $"app_id={appId}" +
                   "&method=alipay.trade.wap.pay" +
                   "&format=json" +
                   "&charset=utf-8" +
                   "&sign_type=RSA2" +
                   $"&timestamp={Uri.EscapeDataString(timestamp)}" +
                   "&version=1.0" +
                   "&notify_url=https://your-domain.com/api/paylinks/alipay-notify" +
                   "&return_url=https://your-domain.com/pay/result" +
                   $"&biz_content={Uri.EscapeDataString(bizContent)}" +
                   $"&sign={Uri.EscapeDataString(sign)}";
        }

        /// <summary>
        /// 构建支付宝H5签名内容
        /// </summary>
        private string BuildAlipayH5SignContent(Order order, PaymentRecord paymentRecord)
        {
            var parameters = new SortedDictionary<string, string>
            {
                ["app_id"] = _config.Alipay.AppId,
                ["biz_content"] = System.Text.Json.JsonSerializer.Serialize(new
                {
                    out_trade_no = paymentRecord.PaymentNo,
                    product_code = "QUICK_WAP_WAY",
                    total_amount = order.PayAmount.ToString("0.00"),
                    subject = "订单支付"
                }),
                ["charset"] = "utf-8",
                ["format"] = "json",
                ["method"] = "alipay.trade.wap.pay",
                ["notify_url"] = "https://your-domain.com/api/paylinks/alipay-notify",
                ["return_url"] = "https://your-domain.com/pay/result",
                ["sign_type"] = "RSA2",
                ["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                ["version"] = "1.0"
            };

            return string.Join("&", parameters.Select(p => $"{p.Key}={p.Value}"));
        }

        /// <summary>
        /// 根据订单号获取订单
        /// </summary>
        private async Task<Order?> GetOrderByOrderNoAsync(string orderNo)
        {
            return await _context.Orders
                .Include(o => o.Items)
                .FirstOrDefaultAsync(o => o.OrderNo == orderNo);
        }

        /// <summary>
        /// 创建支付记录
        /// </summary>
        private async Task<PaymentRecord> CreatePaymentRecordAsync(Order order, string paymentMethod)
        {
            var paymentRecord = new PaymentRecord
            {
                OrderId = order.Id,
                OrderNo = order.OrderNo,
                PaymentNo = $"PAY{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}",
                PaymentAmount = order.PayAmount,
                PaymentStatus = (int)PaymentStatus.Pending,
                PaymentMethod = paymentMethod,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now
            };

            _context.PaymentRecords.Add(paymentRecord);
            await _context.SaveChangesAsync();

            return paymentRecord;
        }

        /// <summary>
        /// 验证回调签名
        /// </summary>
        private bool VerifyNotifySignature(string notifyData)
        {
            // 这里应该实现微信支付V3的签名验证
            // 为了简化，暂时返回true
            // 实际项目中需要按照微信支付文档实现
            return true;
        }

        /// <summary>
        /// 获取交易状态描述
        /// </summary>
        private string GetTradeStateDesc(string tradeState)
        {
            return tradeState switch
            {
                "SUCCESS" => "支付成功",
                "REFUND" => "转入退款",
                "NOTPAY" => "未支付",
                "CLOSED" => "已关闭",
                "REVOKED" => "已撤销",
                "USERPAYING" => "用户支付中",
                "PAYERROR" => "支付失败",
                _ => "未知状态"
            };
        }

        #endregion
    }

    /// <summary>
    /// 微信支付回调数据
    /// </summary>
    public class WeChatPayNotify
    {
        public string AppId { get; set; } = string.Empty;
        public string MchId { get; set; } = string.Empty;
        public string OutTradeNo { get; set; } = string.Empty;
        public string TransactionId { get; set; } = string.Empty;
        public string TradeState { get; set; } = string.Empty;
        public string SuccessTime { get; set; } = string.Empty;
    }

    /// <summary>
    /// 微信退款回调数据
    /// </summary>
    public class WeChatPayRefundNotify
    {
        public string AppId { get; set; } = string.Empty;
        public string MchId { get; set; } = string.Empty;
        public string OutRefundNo { get; set; } = string.Empty;
        public string RefundId { get; set; } = string.Empty;
        public string RefundStatus { get; set; } = string.Empty;
        public string SuccessTime { get; set; } = string.Empty;
    }
} 